<!DOCTYPE html>
<html lang="en">

<head>
    <title>three.js webgl - mirror</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link type="text/css" rel="stylesheet" href="font.css">
    <style>
        html,
        body {
            height: 100%;
            width: 100%;
        }

        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
<div id="app">
    <div id="container" style="width:100%;height:100vh;position:relative; overflow: hidden;"></div>
</div>
<!-- <script src="main.js" async type="module"></script>
    <script src="movie.js" type="module" ></script> -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> -->
<script type="module">
    import * as THREE from 'https://unpkg.com/three@0.120.1/build/three.module.js';
    import {OrbitControls} from 'https://unpkg.com/three@0.120.1/examples/jsm/controls/OrbitControls';

    let renderer, camera, scene, light, controls,group, radius = 5, groupDots, groupLines, groupHalo, aGroup;
    const Dom = document.querySelector('#container');
    const width = Dom.clientWidth, height = Dom.clientHeight;
    const globeTextureLoader = new THREE.TextureLoader();
    group = new THREE.Group();
    groupDots = new THREE.Group();
    groupLines = new THREE.Group();
    groupHalo = new THREE.Group();
    aGroup = new THREE.Group();
    /**
     * @description 初始化渲染场景
     */
    function initRenderer() {
        renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( width, height );
        const containerDom = document.querySelector( '#container' );
        containerDom.appendChild( renderer.domElement );
    }
    /**
     * @description 初始化相机
     */
    function initCamera() {
        camera = new THREE.PerspectiveCamera( 45, width / height, 1, 10000 );
        camera.position.set( 5, - 20, 200 );
        camera.lookAt( 0, 3, 0 );
        window.camera = camera;
    }
    /**
     * @description 初始化场景
     */
    function initScene() {
        scene = new THREE.Scene();
        scene.background = new THREE.Color( 0x020924 );
        scene.fog = new THREE.Fog( 0x020924, 200, 1000 );
        window.scene = scene;
    }
    /**
     * 初始化用户交互
     **/
    function initControls() {
        controls = new OrbitControls( camera, renderer.domElement );
        // 使动画循环使用时阻尼或自转 意思是否有惯性
        controls.enableDamping = true;
        //是否可以缩放
        controls.enableZoom = true;
        //是否自动旋转
        controls.autoRotate = false;
        controls.autoRotateSpeed = 2;
        //是否开启右键拖拽
        controls.enablePan = true;
    }
    // 经纬度转地球坐标
    function createPosition(lnglat) {
        let spherical = new THREE.Spherical;
        spherical.radius = radius;
        const lng = lnglat[0];
        const lat = lnglat[1];
        const theta = (lng + 90) * (Math.PI / 180);
        const phi = (90 - lat) * (Math.PI / 180);
        spherical.phi = phi; //方位角
        spherical.theta = theta; //倾斜角
        let position = new THREE.Vector3();
        position.setFromSpherical(spherical);
        return position;
    }
    /**
     * @description 初始化光
     */
    function initLight() {
        const ambientLight = new THREE.AmbientLight( 0xcccccc, 1.1 );
        scene.add( ambientLight );
        var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.2 );
        directionalLight.position.set( 1, 0.1, 0 ).normalize();
        var directionalLight2 = new THREE.DirectionalLight( 0xff2ffff, 0.2 );
        directionalLight2.position.set( 1, 0.1, 0.1 ).normalize();
        scene.add( directionalLight );
        scene.add( directionalLight2 );
        var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444, 0.2 );
        hemiLight.position.set( 0, 1, 0 );
        scene.add( hemiLight );
        var directionalLight = new THREE.DirectionalLight( 0xffffff );
        directionalLight.position.set( 1, 500, - 20 );
        directionalLight.castShadow = true;
        directionalLight.shadow.camera.top = 18;
        directionalLight.shadow.camera.bottom = - 10;
        directionalLight.shadow.camera.left = - 52;
        directionalLight.shadow.camera.right = 12;
        scene.add(directionalLight);
    }
    function initBackground(){
        /**
         *  随机生成10000个坐标点，设置不同的颜色
         */
        const positions = [];
        const colors = [];
        const geometry = new THREE.BufferGeometry();
        for (var i = 0; i < 10000; i ++) {
            var vertex = new THREE.Vector3();
            vertex.x = Math.random() * 2 - 1;
            vertex.y = Math.random() * 2 - 1;
            vertex.z = Math.random() * 2 - 1;
            positions.push( vertex.x, vertex.y, vertex.z );
            var color = new THREE.Color();
            color.setHSL( Math.random() * 0.2 + 0.5, 0.55, Math.random() * 0.25 + 0.55 );
            colors.push( color.r, color.g, color.b );
        }
        geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
        geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
        /**
         *  ParticleBasicMaterial 基础粒子材质用来搭配例子系统，这里我们可以设置粒子的大小，贴图，透明度等设置详细如下
         * */
        function getTexture() {
            return new THREE.TextureLoader().load('./images/particle2.png');
        }
        var starsMaterial = new THREE.ParticleBasicMaterial( {
            map: getTexture(),
            size: 1,
            transparent: true,
            opacity: 1,
            vertexColors: true, //true：且该几何体的colors属性有值，则该粒子会舍弃第一个属性--color，而应用该几何体的colors属性的颜色
            blending: THREE.AdditiveBlending,
            sizeAttenuation: true
        } );
        /**
         *  把上面生成的几何体geometry 以及材质ParticleBasicMaterial来生成一个ParticleSystem，如下：
         * */
        let stars = new THREE.ParticleSystem( geometry, starsMaterial );
        stars.scale.set( 300, 300, 300 );
        scene.add( stars );
    }
    function initObject(){
        // 光环
        globeTextureLoader.load('./images/halo.png', function (texture) {
            var geometry = new THREE.PlaneGeometry(14, 14); //矩形平面
            var material = new THREE.MeshLambertMaterial({
                map: texture, //给纹理属性map赋值
                transparent: true,
                side: THREE.DoubleSide, //两面可见
                depthWrite: false
            }); //材质对象
            var mesh = new THREE.Mesh(geometry, material); //网格模型对象
            groupHalo.add(mesh);
        });

        // 小地球
        globeTextureLoader.load('./images/smallEarth.png', function (texture) {
            var p1 = new THREE.Vector3( - 7, 0, 0 );
            var p2 = new THREE.Vector3( 7, 0, 0 );
            const points = [ p1,p2];
            const geometry = new THREE.BufferGeometry().setFromPoints( points );
            var material = new THREE.PointsMaterial( {
                map: texture,
                transparent: true,
                side: THREE.DoubleSide,
                size: 1,
                depthWrite: false
            } );
            var earthPoints = new THREE.Points( geometry, material );
            groupHalo.add( earthPoints );
        });
        groupHalo.rotation.set(1.9, 0.5, 1);
        scene.add(groupHalo)

        //  地球
        globeTextureLoader.load( './images/earth2.jpg', function ( texture ) {
            var globeGgeometry = new THREE.SphereGeometry( radius, 100, 100 );
            var globeMaterial = new THREE.MeshStandardMaterial( { map: texture } );
            var globeMesh = new THREE.Mesh( globeGgeometry, globeMaterial );
            group.rotation.set( 0.5, 2.9, 0.1 );
            group.add( globeMesh );
        } );
        scene.add( group );


    }
    /**
     * 窗口变动
     **/
    function onWindowResize() {
        camera.aspect = innerWidth / innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( innerWidth, innerHeight );
        renders();
    }

    /**
     * @description 渲染
     */
    function renders() {
        renderer.clear();
        renderer.render( scene, camera );
    }

    /**
     * 更新
     **/
    function animate() {
        window.requestAnimationFrame( () => {
            if (controls) controls.update();
            groupHalo.rotation.z = groupHalo.rotation.z + 0.01;
            group.rotation.y = group.rotation.y + 0.001;
            renders();
            animate();
        } );
    }

    window.onload = () => {
        initRenderer();
        initCamera();
        initScene();
        initLight();
        initControls();
        initBackground();
        initObject();
        animate();
        window.addEventListener('resize', onWindowResize, false);
    };
</script>
</body>

</html>